/**
 * WebController.m by Giraldo Rosales.
 * Visit www.liquidgear.net for documentation and updates.
 *
 *
 * Copyright (c) 2009 Nitrogen Design, Inc. All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 **/

#import "CJSONDeserializer.h"
#import "CJSONSerializer.h"
#import "LiquidGearAppDelegate.h"
#import "Utils.h"
#import "WebController.h"

#if LG_USE_ACCELERATION
#import "Accelerometer.h"
#endif

#if LG_USE_ADMOB
#import "AdMob.h"
#endif

#if LG_USE_EMAIL
#import "Email.h"
#endif

#if LG_USE_CONTACTS
#import "Contact.h"
#endif

#if LG_USE_DATABASE
#import "Database.h"
#endif

#if LG_USE_IMAGE
#import "Image.h"
#endif

#import "Info.h"

#if LG_USE_LOCATION
#import "Location.h"
#endif

#if LG_USE_NAVBAR
#import "NavBar.h"
#endif

#if LG_USE_NOTIFY
#import "Notify.h"
#endif

#if LG_USE_SOUND
#import "Sound.h"
#endif

#if LG_USE_TABBAR
#import "TabBar.h"
#endif

#if LG_USE_YOUTUBE
#import "YouTubeDelegate.h"
#endif

@implementation WebController

@synthesize webView, imageView, appURL;

#if LG_USE_ACCELERATION
@synthesize accelerometer;
#endif

#if LG_USE_ADMOB
@synthesize admob;
#endif

#if LG_USE_DATABASE
@synthesize db;
#endif

#if LG_USE_EMAIL
@synthesize mail;
#endif

#if LG_USE_IMAGE
@synthesize image;
#endif

#if LG_USE_LOCATION
@synthesize location;
#endif

#if LG_USE_NAVBAR
@synthesize navBar;
#endif

#if LG_USE_SOUND
@synthesize sound;
#endif

#if LG_USE_TABBAR
@synthesize tabs;
#endif

#if LG_USE_YOUTUBE
@synthesize ytView;
#endif

- (id)init:(CGRect)rect {
	webView				= [[UIWebView alloc] initWithFrame:rect];
	return self;
}

- (void)loadView {
	NSLog(@"WebController::loadView");
	
	webView.delegate	= self;
#ifdef LG_DEBUG
	[self startJSLogger];
#endif
	
	self.view = webView;
}

-(void) viewDidLoad {
	NSLog(@"WebController::viewDidLoad");
	[webView loadRequest:[NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0]];
}

- (void)webViewDidStartLoad:(UIWebView *)theWebView {
	NSLog(@"WebController::webViewDidStartLoad");
	[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}

- (void)webViewDidFinishLoad:(UIWebView *)theWebView {
	NSLog(@"WebController::webViewDidFinishLoad");
	//[webView stringByEvaluatingJavaScriptFromString:@"lg.onLoad('LGInit');"];
	//Hide throbber in status bar
	[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

- (void)resizeValue {
	//Calback webView dimensions
	NSDictionary *callback	= [NSDictionary dictionaryWithObjectsAndKeys:
														 [[[NSString alloc] autorelease] initWithFormat:@"%f", webView.frame.size.width], @"width",
														 [[[NSString alloc] autorelease] initWithFormat:@"%f", webView.frame.size.height], @"height",
														 nil
														 ];
	
	[[[Utils alloc] autorelease] jsCall:webView type:@"info" data:callback directCall:nil];
}


/*
 * Start Loading Request
 * This is where most of the magic happens... We take the request(s) and process the response.
 * From here we can re direct links and other protocalls to different internal methods.
 *
 */
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
	NSURL * url = [request URL];	
	NSLog(@"url: %@", url);
	
	NSString *urlHost = [url host];
	NSString *appHost = [appURL host];
	NSRange range			= [urlHost rangeOfString:appHost options:NSCaseInsensitiveSearch];
	NSArray *appLinks	= [NSArray arrayWithObjects:@"tel", @"sms", @"mailto", @"http://maps.google.com", nil];
	
	if ([[url scheme] isEqualToString:@"lg"]) {
		NSString *command			= [url host];
		NSString *jsCallback	= nil;
		
		//Deserialize parameters
		int varCount	= 0;
		NSDictionary *vars	= nil;
		
		if([[url query] length] > 0) {
			NSString *jsonString	= [NSString stringWithFormat:@"%@", [[[Utils alloc] autorelease] urldecode:[url query]]];
			NSData *jsonData			= [jsonString dataUsingEncoding:NSUTF8StringEncoding];
			
			vars			= [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:nil];
			varCount	= [vars count];
		}
		
		if([command isEqualToString:@""]){
			NSLog(@"Command is blank");
		}
#if LG_USE_ACCELERATION
		/***********************************
		 * Accelerometer
		 ***********************************/
		else if([command isEqualToString:@"accelerometer"]){
			bool activate	= [vars valueForKey:@"activate"] ? [[vars valueForKey:@"activate"] boolValue] : FALSE;
			float update	= [vars valueForKey:@"update"] ? [[vars valueForKey:@"update"] floatValue] : 0.025;
			
			if(accelerometer == nil) {
				accelerometer = [[Accelerometer alloc] initWithControl:self];
			}
			
			if(activate) {
				[accelerometer turnOn:update];
			} else {
				[accelerometer turnOff];
			}
		}
#endif
		
#if LG_USE_ADMOB
		/***********************************
		 * AdMob
		 ***********************************/
		if([command isEqualToString:@"admob"]){
			NSString *action			= [vars valueForKey:@"action"] ? [vars valueForKey:@"action"] : @"Undefined";
			
			if([action isEqualToString:@"hide"]) {
				[admob hideBar];
			}
			else if([action isEqualToString:@"show"]) {
				NSString *position	= [vars valueForKey:@"position"] ? [vars valueForKey:@"position"] : @"top";
				[admob showBar:position];
			}
			
			[self resizeValue];
		}
#endif
		
		
#if LG_USE_EMAIL
		/***********************************
		 * Email
		 ***********************************/
		if([command isEqualToString:@"email"]){
			NSLog(@"send email");
			
			NSString *action			= [vars valueForKey:@"action"] ? [vars valueForKey:@"action"] : @"Undefined";
			NSLog(@"email action: %@", action);
			if(mail	== nil) {
				mail = [[Email alloc] initWithController:self];
			}
			
			if([action isEqualToString:@"send"]) {
				[mail sendEmail];
			}
			
			[self nextCall];
		}
#endif
		
#if LG_USE_CONTACTS
		/***********************************
		 * Contacts
		 ***********************************/
		else if([command isEqualToString:@"contacts"]) {
			NSString *what		= nil;
			NSString *cat			= nil;
			NSString *sortBy	= nil;
			
			if(vars != nil) {
				what		= [vars valueForKey:@"value"] ? [vars valueForKey:@"value"] : nil;
				cat			= [vars valueForKey:@"category"] ? [vars valueForKey:@"category"] : nil;
				sortBy	= [vars valueForKey:@"sort"] ? [vars valueForKey:@"sort"] : @"first";
			}
			
			[[[[Contact alloc] autorelease] initWithController:self] getContacts:what category:cat sort:sortBy];
		}
#endif
		
#if LG_USE_DATABASE
		/***********************************
		 * Database
		 ***********************************/
		else if([command isEqualToString:@"database"]) {
			NSString *action	= [vars valueForKey:@"action"] ? [vars valueForKey:@"action"] : @"undefined";
			NSString *query		= @"";
			
			if([action isEqualToString:@"open"]) {
				NSString *type	= [vars valueForKey:@"type"] ? [vars valueForKey:@"type"] : @"memory";
				NSString *name	= [vars valueForKey:@"name"] ? [vars valueForKey:@"name"] : @"";
				
				if([type isEqualToString:@"file"]) {
					NSBundle *mainBundle	= [NSBundle mainBundle];
					NSString *dbURL				= [mainBundle pathForResource:name ofType:@"sqlite"];
					db	= [[Database alloc] initWithController:self path:dbURL];
				} else if([type isEqualToString:@"memory"]) {
					db	= [[Database alloc] initInMemory];
				}
			}
			else if([action isEqualToString:@"execute"]) {
				query	= [vars valueForKey:@"query"] ? [vars valueForKey:@"query"] : @"";
				[db execute:query];
			}
			else if([action isEqualToString:@"query"]) {
				query	= [vars valueForKey:@"query"] ? [vars valueForKey:@"query"] : @"";
				[db query:query];
			}
			
			[self nextCall];
		}
#endif
		
#if LG_USE_IMAGE
		/***********************************
		 * Images
		 ***********************************/
		else if([command isEqualToString:@"image"]) {
			NSString *type			= [vars valueForKey:@"type"] ? [vars valueForKey:@"type"] : @"library";
			NSString *edit			= [vars valueForKey:@"edit"] ? [vars valueForKey:@"edit"] : @"no";
			NSString *quality		= [vars valueForKey:@"quality"] ? [vars valueForKey:@"quality"] : @"0.75";
			NSString *url				= [vars valueForKey:@"url"] ? [vars valueForKey:@"url"] : @"local";
			NSString *filename	= [vars valueForKey:@"filename"] ? [vars valueForKey:@"filename"] : @"lg_image.jpg";
			
			if([type isEqualToString:@"library"] || [type isEqualToString:@"camera"] || [type isEqualToString:@"web"]) {
				if(image == nil) {
					image = [[Image alloc] initWithController:self];
				}
				[image getImage:type edit:edit name:filename url:url quality:quality];
			}
		}
#endif
		
#if LG_USE_INFO
		/***********************************
		 * Information
		 ***********************************/
		else if([command isEqualToString:@"info"]) {
			[[[Info alloc] initWithControl:self] getInfo];
		}
#endif
		
#if LG_USE_LOCATION
		/***********************************
		 * Location
		 ***********************************/
		else if ([command isEqualToString:@"location"]) {
			bool activate	= [vars valueForKey:@"activate"] ? [[vars valueForKey:@"activate"] boolValue] : FALSE;
			float update	= [vars valueForKey:@"update"] ? [[vars valueForKey:@"update"] floatValue] : 0.025;
			int accuracy	= [vars valueForKey:@"accuracy"] ? [[vars valueForKey:@"accuracy"] intValue] : 10;
			
			if(location == nil) {
				location = [[Location alloc] initWithController:self accuracy:accuracy];
			}
			
			if(activate) {
				[location.locationManager startUpdatingLocation];
			} else {
				[location.locationManager stopUpdatingLocation];	
			}
		}
#endif
		
#if LG_USE_NAVBAR
		/***********************************
		 * Navigation Bar
		 ***********************************/
		else if([command isEqualToString:@"navigation"]) {
			if(varCount > 0) {
				//Get message
				NSString *action			= [vars valueForKey:@"action"] ? [vars valueForKey:@"action"] : @"Undefined";
				NSString *title				= [vars valueForKey:@"title"] ? [vars valueForKey:@"title"] : @"Untitled";
				NSString *desc				= [vars valueForKey:@"desc"] ? [vars valueForKey:@"desc"] : @"";
				NSString *leftTitle		= [vars valueForKey:@"leftTitle"] ? [vars valueForKey:@"leftTitle"] : @"";
				NSString *leftCall		= [vars valueForKey:@"leftCall"] ? [vars valueForKey:@"leftCall"] : @"";
				NSString *rightTitle	= [vars valueForKey:@"rightTitle"] ? [vars valueForKey:@"rightTitle"] : @"";
				NSString *rightCall		= [vars valueForKey:@"rightCall"] ? [vars valueForKey:@"rightCall"] : @"";
				NSString *hideBack		= [vars valueForKey:@"hideBack"] ? [vars valueForKey:@"hideBack"] : @"";
				BOOL hideNav					= [vars valueForKey:@"hideNav"] ? [[vars valueForKey:@"hideNav"] boolValue] : FALSE;
				
				if([action isEqualToString:@"show"]) {
					int barStyle				= [vars valueForKey:@"barStyle"] ? [[vars valueForKey:@"barStyle"] intValue] : 0;
					UIColor *tintColor	= [vars valueForKey:@"tintColor"] ? [[[Utils alloc] autorelease] txtToColor:[vars valueForKey:@"tintColor"]] : [UIColor lightGrayColor];
					BOOL translucent		= [vars valueForKey:@"translucent"] ? [[vars valueForKey:@"translucent"] boolValue] : FALSE;
					
					[navBar showBar:barStyle tintColor:tintColor translucent:translucent];
				}
				else if([action isEqualToString:@"hide"]) {
					[navBar hideBar];
				}
				else if([action isEqualToString:@"add"]) {
					[navBar addNavItem:title description:desc leftTitle:leftTitle leftCall:leftCall rightTitle:rightTitle rightCall:rightCall hideBack:hideBack];
				}
			}
			
			[self nextCall];
		}
#endif
		
#if LG_USE_NOTIFY
		/***********************************
		 * Notifications
		 ***********************************/
		else if([command isEqualToString:@"notifyAlert"]) {
			if(varCount > 0) {
				//Get message
				NSString *msg		= [vars valueForKey:@"msg"] ? [vars valueForKey:@"msg"] : @"Undefined";
				NSString *title = [vars valueForKey:@"title"] ? [vars valueForKey:@"title"] : @"Alert";
				NSString *btn		= [vars valueForKey:@"btn"] ? [vars valueForKey:@"btn"] : @"Ok";
				
				[[[Notify alloc] autorelease] alert:msg title:title btn:btn];
			}
			[self nextCall];
		}
		
		//Make the device vibrate, this is now part of the notifier object.
		else if([command isEqualToString:@"notifyVibrate"]){
			[[[Notify alloc] autorelease] vibrate];
			[self nextCall];
		}
		
		//Add an application badge number
		else if([command isEqualToString:@"notifyBadge"]){
			NSString *label = [vars valueForKey:@"label"] ? [vars valueForKey:@"label"] : 0;
			
			int badgeNum = [label intValue];
			[[[Notify alloc] autorelease] badge:badgeNum];
			[self nextCall];
		}
#endif
		
#if LG_USE_SOUND
		/***********************************
		 * SOUND
		 ***********************************/
		else if ([command isEqualToString:@"sound"]) {
			NSString *file				= [vars valueForKey:@"file"] ? [vars valueForKey:@"file"] : nil;
			
			if([file length] > 0) {
				[[[Sound alloc] autorelease] play:file];
			} else {
				NSLog(@"No sound file specified.");
			}
			
			[self nextCall];
		}
#endif
		
#if LG_USE_TABBAR
		/***********************************
		 * Tabs
		 ***********************************/
		else if([command isEqualToString:@"tabs"]){
			NSString *action	= [vars valueForKey:@"action"] ? [vars valueForKey:@"action"] : @"";
			int btn						= [vars valueForKey:@"btn"] ? [[vars valueForKey:@"btn"] intValue] : 1;
			
			if([action isEqualToString:@"add"]) {
				NSString *title			= [vars valueForKey:@"title"] ? [vars valueForKey:@"title"] : @"";
				NSString *icon			= [vars valueForKey:@"icon"] ? [vars valueForKey:@"icon"] : @"";
				NSString *callback	= [vars valueForKey:@"callback"] ? [vars valueForKey:@"callback"] : @"";
				[tabs addTab:btn title:title icon:icon callback:callback];
				//[self nextCall];
			}
			else if([action isEqualToString:@"show"]) {
				[tabs showBar];
				//[self resizeValue];
			}
			else if([action isEqualToString:@"hide"]) {
				[tabs hideBar];
				//[self resizeValue];
			}
			else if([action isEqualToString:@"badge"]) {
				NSString *value		= [vars valueForKey:@"value"] ? [[vars valueForKey:@"value"] stringValue] : @"";
				[tabs setBadge:btn value:value];
				//[self nextCall];
			}
			else if([action isEqualToString:@"remove"]) {
				[tabs removeTab:btn];
				//[self nextCall];
			}
			else if([action isEqualToString:@"select"]) {
				[tabs setSelected:btn];
				//[self nextCall];
			} else {
				//[self nextCall];
			}
			[self nextCall];
		}
#endif
		
		/***********************************
		 * Throbber
		 ***********************************/
		else if([command isEqualToString:@"throbber"]){
			NSString *action	= [vars valueForKey:@"action"] ? [vars valueForKey:@"action"] : @"";
			NSLog(@"throbber action: %@", action);
			if([action isEqualToString:@"show"]) {
				[self startThrobber];
			}
			else if([action isEqualToString:@"hide"]) {
				[self stopThrobber];
			}
			
			[self nextCall];
		}
		
#if LG_USE_VIDEO
		/***********************************
		 * Video
		 ***********************************/
		else if([command isEqualToString:@"video"]){
			//Video *video = [[Video alloc] initMoviePlayer];
			//[video loadRe
		}
#endif
		else {
			[self nextCall];
		}
		
		return NO;
	}
	
	else if ([[url scheme] isEqualToString:@"local"]) {
		return NO;
	}
	
	//Internal links
	else if ([appLinks containsObject:[url scheme]]) {
		[[UIApplication sharedApplication] openURL:url];
		[self nextCall];
		return NO;
	}
	
	//Other links
	else {
		if (range.location == NSNotFound) {
			NSLog(@"NOTFOUND URL");
			[[UIApplication sharedApplication] openURL:url];
		}
	}
	
	return YES;
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
	NSLog(@"didFailLoadWithError");
	if ([error code] != NSURLErrorCancelled) {
		//[[[Notify alloc] alert:error.localizedDescription] autorelease];
	}
}

- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
	// Release anything that's not essential, such as cached data
}

- (void)nextCall {	
	[webView stringByEvaluatingJavaScriptFromString:@"lg.nextCall();"];
}

- (void)startThrobber {
	if([webView viewWithTag:23] != nil) {
		return;
	}
	
	//Create the first status image and the indicator view
	Utils *util											= [Utils alloc];
	UIColor *throbColor							= [util txtToColor:LG_THROB_COLOR];
	UIImage *statusImage						= [util tintImage:[UIImage imageNamed:@"throbber1.png"] color:throbColor];
	UIImageView *activityImageView	= [[UIImageView alloc] initWithImage:statusImage];
	
	//Add more images which will be used for the animation
	
	activityImageView.animationImages = [NSArray arrayWithObjects:
																			 [util tintImage:[UIImage imageNamed:@"throbber1.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber2.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber3.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber4.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber5.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber6.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber7.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber8.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber9.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber10.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber11.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber12.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber13.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber14.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber15.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber16.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber17.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber18.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber19.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber20.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber21.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber22.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber23.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber24.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber25.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber26.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber27.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber28.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber29.png"] color:throbColor],
																			 [util tintImage:[UIImage imageNamed:@"throbber30.png"] color:throbColor],
																			 nil];
	
	activityImageView.animationDuration	= 1.15;
	activityImageView.frame							= CGRectMake(self.view.frame.size.width/2-statusImage.size.width/2, self.view.frame.size.height/2-statusImage.size.height/2, statusImage.size.width, statusImage.size.height);
	activityImageView.tag								= 23;
	
	//Start animating
	[activityImageView startAnimating];
	
	//Show throbber
	[webView addSubview:activityImageView];
}

- (void)stopThrobber {
	if([webView viewWithTag:23] == nil) {
		return;
	}
	
	UIView *activityImageView	= [webView viewWithTag:23];
	[activityImageView removeFromSuperview];
	[activityImageView release];
}

#ifdef LG_DEBUG
- (void) startJSLogger {
  NSString *createLoggerJS = @"console = { msgs: new Array(), log: function(msg) { console.msgs.push(msg); }, shift: function() { return console.msgs.shift(); } };";
  
	[webView stringByEvaluatingJavaScriptFromString:createLoggerJS];
  [self readJSLogger];
}

- (void) readJSLogger {
  NSString *msg = NULL;
  
	while( (msg = [webView stringByEvaluatingJavaScriptFromString:@"console.shift();"]) != NULL && [msg length] != 0) {
    NSLog(@"JS: %@", msg);
  }
	
  [self performSelector:@selector(readJSLogger) withObject:nil afterDelay:0.1];
}
#endif

- (void)dealloc {
#if LG_USE_DATABASE
	[db release];
#endif
						
#if LG_USE_SOUND
	[sound release];
#endif
	
#if LG_USE_IMAGE
	[image release];
#endif
	
#if LG_USE_LOCATION
	[location release];
#endif
	
#if LG_USE_ACCELERATION
	[accelerometer release];
#endif
	
	[webView release];
	[super dealloc];
}

@end
